open Ast_printer
open Type

let print_path = function
	| (pList, p) -> print_string ("'" ^ ( String.concat "." pList ) ^ ( if pList != [] then "." else "" ) ^ p ^ "'" )

let print_field_access = function
	| NormalAccess -> print_string " [ NormalAccess ]"
	| NoAccess -> print_string "[ NoAccess ]"
	| ResolveAccess -> print_string "[ ResolveAccess ]"
	| CallAccess ( str ) -> print_string ( "[ CallAccess : '" ^ str ^ "' ]" )
	| MethodAccess ( cond ) -> print_string ( "[ MethodAccess : is " ^ (if cond then "" else "not") ^ " dynamic ]" )
	| InlineAccess -> print_string "[ InlineAccess ]"
	| NeverAccess -> print_string "[ NeverAccess ]"

let print_const = function
	| TInt ( i ) -> print_string "[ TInt : " ; print_string ("'" ^ (Int32.to_string i) ^ "' ]")
	| TFloat ( f ) -> print_string "[ TFloat : " ; print_string ("'" ^ f ^ "' ]")
	| TString ( s ) -> print_string "[ TString : " ; print_string ("'" ^ s ^ "' ]")
	| TBool ( b ) -> print_string "[ TBool : " ; print_string ("'" ^ ( string_of_bool b ) ^ "' ]")
	| TNull -> print_string "[ TNull ]"
	| TThis -> print_string "[ TThis ]"
	| TSuper -> print_string "[ TSuper ]"

let rec print_type = function
	| TMono ( t_option_ref ) -> print_string "[ TMono -> " ; (match !t_option_ref with None -> () | Some t -> print_type t);print_string " ]"
	| TEnum ( ( enum , params ) ) -> print_string "[ TEnum : " ; print_path enum.e_path; print_string "( " ; print_params params; print_string " ) ]";
	| TInst ( ( cla , params ) ) -> print_string "[ TInst : " ; print_path cla.cl_path ; print_string "( "; print_params params ; print_string " ) ]";
	| TType ( ( def , params ) ) -> print_string "[ TType : " ; print_path def.t_path ; print_string "( "; print_params params; print_string " ) ]";
	| TFun ( ( list , t ) ) -> print_string "[ TFun " ;
			let print_triple = function ( a, b, c ) ->
						print_string ("( Parameter '" ^ a ^ "' is "
								^ ( if b then "" else "not" ) ^ " optional and of type ");
						print_type c ; print_string " ) "
			in List.iter print_triple list ; print_string " returns "; print_type t; print_string " ]"
	| TAnon ( anon ) -> print_string "[ TAnon : " ; print_anon anon;print_string " ]"
	| TDynamic ( t ) -> print_string "[ TDynamic ]" ; 
	| TLazy ( f_ref ) -> print_string "[ TLazy -> " ; print_type ( !f_ref() ); print_string " ]"

and print_params p = List.iter print_type p

and print_func f =
	print_string "[ FType : " ;
	print_type f.tf_type ;
	print_string " ]";
	
	print_string "[ FArguments : " ;
	let print_triple = function ( str , const_option , t ) ->
				print_string ("( '" ^ str ^ "' ") ;
				(match const_option with None -> () | Some const -> print_string "with value " ; print_const const );
				print_string "of type " ; print_type t; print_string " )";
	in List.iter print_triple f.tf_args ;
	print_string " ]";
	
	print_string "[ FExpression : " ;
	print_expr f.tf_expr;
	print_string " ]"

and print_anon_status = function
	| Closed -> print_string "[ Closed ]"
	| Opened -> print_string "[ Openend ]"
	| Const -> print_string "[ Const ]"
	| Statics ( cla ) -> print_string "[ Statics : " ; print_path cla.cl_path ;print_string " ]"
	| EnumStatics ( enum ) -> print_string "[ EnumStatics : " ; print_path enum.e_path; print_string " ]"

and print_anon a =
	print_string "[ AFields : " ;
	let print_scf s cf =
		print_string ("( '" ^ s ^ "' , ") ;
		print_string (cf.cf_name ^ " )")
	in PMap.iter print_scf a.a_fields ;
	print_string " ]";
	
	print_string "[ Anon_status : " ;
	print_anon_status !( a.a_status );
	print_string " ]"

and print_expr e =
	print_type e.etype ;
	print_string " => ";
	
	match e.eexpr with
			| TConst ( const ) ->
					print_string "[ TConst : " ;
					print_const const;
					print_string " ]"
			| TLocal ( str ) ->
					print_string ("[ TLocal : '" ^ str ^ "' ]") ;
			| TEnumField ( enum , str ) ->
					print_string ("[ TEnumField : '" ^ str ^ "' ]") ;
			| TArray ( expr, expt ) ->
					print_string "[ TArray : " ;
					print_expr expr ;
					print_expr expt ;
					print_string " ]"
			| TBinop ( bi, expr, expt ) ->
					print_string "[ TBinop : " ;
					print_binop bi ;
					print_expr expr ;
					print_expr expt;
					print_string " ]"
			| TField ( expr, str ) ->
					print_string " [ TField : " ;
					print_string ("'" ^ str ^ "' => ");
					print_expr expr ;
					print_string " ]"
			| TClosure ( expr, str ) ->
					print_string "[ TClosure : " ;
					print_string ("'" ^ str ^ "' => ");
					print_expr expr ;
					print_string " ]"
			| TTypeExpr ( m_type ) ->
					print_string "[ TTypeExpr : " ;
					print_module_type m_type;
					print_string " ]"
			| TParenthesis ( expr ) ->
					print_string "[ TParenthesis : " ;
					print_expr expr;
					print_string " ]"
			| TObjectDecl ( list ) ->
					print_string "[ TObjectDecl : " ;
					let print_tuple = function ( a, b ) ->
								print_string ("'" ^ a ^ "' => ") ;
								print_expr b
					in List.iter print_tuple list
			| TArrayDecl ( expr_list ) ->
					print_string "[ TArrayDecl : " ;
					List.iter print_expr expr_list;
					print_string " ]"
			| TCall ( expr , expr_list ) ->
					print_endline "[ TCall : " ;
					print_expr expr ;
					List.iter print_expr expr_list;
					print_string " ]"
			| TNew ( cla , params , expr_list ) ->
					print_string "[ TNew : " ;
					print_path cla.cl_path ;
					print_string " ( ";
					print_params params;
					print_string " ) ";
					print_string " ]"
			| TUnop ( uno, uno_flag, expr ) ->
					print_string "[ TUnop : " ;
					print_unop uno ;
					print_unop_flag uno_flag ;
					print_expr expr;
					print_string " ]"
			| TFunction ( func ) ->
					print_string "[ TFunction : " ;
					print_func func;
					print_string " ]"
			| TVars ( list ) ->
					print_string "[ TVars : " ;
					let print_triple = function ( str , t , expr_option ) ->
								print_string ( "( '" ^ str ^ "' of type " ) ;
								print_type t ;
								print_string " => ";
								(match expr_option with None -> print_string "" | Some ( expr ) -> print_expr expr);
								print_string " )"
					in List.iter print_triple list;
					print_string " ]"
			| TBlock ( expr_list ) ->
					print_string "[ TBlock : " ;
					List.iter print_expr expr_list;
					print_string " ]"
			| TFor ( str , t , expr , expt ) ->
					print_string "[ TFor : " ;
					print_string ("'" ^ str ^ "' of type " ) ;
					print_type t ;
					print_string " => ";
					print_expr expr ;
					print_expr expt ;
					print_string " ]"
			| TIf ( expr , expt , expr_option ) ->
					print_string "[ TIf : " ;
					print_expr expr ;
					print_expr expt ;
					( match expr_option with None -> () | Some ( expr ) -> print_expr expr );
					print_string " ]"
			| TWhile ( expr , expt , while_flag ) ->
					print_string "[ TWhile : " ;
					print_expr expr ;
					print_expr expt ;
					print_while_flag while_flag;
					print_string " ]"
			| TSwitch ( expr , list , expr_option ) ->
					print_string "[ TSwitch : " ;
					print_expr expr ;
					let print_tuple = function ( expr_list , expr ) ->
								List.iter print_expr expr_list ;
								print_expr expr
					in List.iter print_tuple list ;
					( match expr_option with None -> () | Some ( expr ) -> print_expr expr );
					print_string " ]"
			| TMatch ( expr , ( enum , params ) , list , expr_option ) ->
					print_string "[ TMatch : " ;
					print_expr expr ;
					print_path enum.e_path ;
					let	print_ile = function ( int_list , sot_list_option , expt ) ->
								( List.iter print_int int_list ) ;
								let print_sot = function ( str_option , t ) ->
											( match str_option with None -> () | Some ( str ) -> print_string ("( '" ^ str ^ "' of type ") ) ;
											print_type t;
											print_string " )"
								in ( match sot_list_option with None -> () | Some ( sot ) -> List.iter print_sot sot ) ;
								print_expr expt
					in List.iter print_ile list ;
					( match expr_option with None -> () | Some ( expr ) -> print_expr expr );
					print_string " ]"
			| TTry ( expr , list ) ->
					print_string "[ TTry : " ;
					print_expr expr ;
					let print_triple = function ( str , t , expr ) ->
								print_string ( "( '" ^ str ^ "' of type " );
								print_type t ;
								print_expr expr;
								print_string " )"
					in List.iter print_triple list ;
					print_string " ]"
			| TReturn ( expr_option ) ->
					print_string "[ TReturn : " ;
					( match expr_option with None -> () | Some ( expr ) -> print_expr expr );
					print_string " ]"
			| TBreak -> print_string "[ TBreak ]"
			| TContinue -> print_string "[ TContinue ]"
			| TThrow ( expr ) ->
					print_string "[ TTrow : " ;
					print_expr expr;
					print_string " ]"
			| TCast ( expr , m_type_option ) ->
					print_string "[ TCast : " ;
					print_expr expr ;
					match m_type_option with None -> () | Some ( m_type ) -> print_module_type m_type ;
									

and print_class_field cf =
	print_string "[ CFName : " ;
	print_string ("'" ^ cf.cf_name ^ "'") ;
	print_endline " ]";
	
	print_string "[ CFType : " ;
	print_type cf.cf_type ;
	print_endline " ]";
	
	print_string "[ CFPublic : " ;
	print_endline (match cf.cf_public with true -> "true ]" | false -> "false ]" );
	
	print_string "[ CFDocumentation : " ;
	print_endline ((match cf.cf_doc with None -> "none" | Some ( doc ) -> doc) ^ " ]");
	
	print_string "[ CFGet : " ;
	print_field_access cf.cf_get ;
	print_endline " ]";
	
	print_string "[ CFSet : " ;
	print_field_access cf.cf_set ;
	print_endline " ]";
	
	print_string "[ CFParameters : " ;
	let print_st = function ( str , t ) ->
				print_string ("'" ^ str ^ "' of type ") ;
				print_type t
	in List.iter print_st cf.cf_params ;
	print_endline " ]";
	
	print_string "[ CFExpression : " ;
	(match cf.cf_expr with None -> () | Some ( expr ) -> print_expr expr);
	print_endline " ]";

and print_class_kind = function
	| KNormal -> print_string "[ KNormal ]"
	| KTypeParameter -> print_string "[ KTypeParameter ]"
	| KExtension ( cla , params ) -> print_string "[ KExtension : " ; print_path cla.cl_path ; print_string " ]"
	| KConstant ( const ) -> print_string "[ KConstant : " ; print_const const; print_string " ]"
	| KGeneric -> print_string "[ KGeneric ]"
	| KGenericInstance ( cla , params ) -> print_string "[ KGenericInstance : " ; print_path cla.cl_path ;print_string " ]"


and print_class cl =
	print_string "{ Class path : " ;
	print_path cl.cl_path ;
	print_endline " }";
	
	print_endline ( "{ Private : " ^ (string_of_bool cl.cl_private) ^ " }" ) ;
	print_endline ( "{ Documentation : " ^ ( match cl.cl_doc with None -> "none }" | Some ( doc ) -> doc ^ " }" ) ) ;
	
	print_string "{ Class kind : " ;
	print_class_kind cl.cl_kind ;
	print_endline " }";
	
	print_endline ( "{ Extern : " ^ ( string_of_bool cl.cl_extern) ^ "}" ) ;
	print_endline ( "{ Interface : " ^ ( string_of_bool cl.cl_interface) ^ " }" ) ;
	
	print_string "{ Parameter Types : " ;
	let print_types = function ( a, b ) ->
				print_string ("( '" ^ a ^ "'") ;
				print_type b;
				print_string " )"
	in List.iter print_types cl.cl_types ;
	print_endline " }";
	
	print_string "{ Super : " ;
	( match cl.cl_super with None -> () | Some ( ( super, params ) ) ->
						print_path super.cl_path; print_params params ) ;
	print_endline " }";
	
	print_string "{ Implements : " ;
	 List.iter (fun ( interface , params ) ->
				print_path interface.cl_path; print_params params) cl.cl_implements ;
	print_endline " }";
	
	print_string "{ Fields : " ;
	let print_sf str field =
		print_string ( "'" ^ str ^ "' => ");
		print_class_field field
	in PMap.iter print_sf cl.cl_fields ;
	print_endline " }";
	
	print_string "{ Statics : " ;
	PMap.iter print_sf cl.cl_statics ;
	print_endline " }";
	
	print_string "{ Dynamic : " ;
	( match cl.cl_dynamic with None -> () | Some ( dyn ) -> print_type dyn ) ;
	print_endline " }";
	
	print_string "{ Array access : " ;
	( match cl.cl_array_access with None -> () | Some ( t ) -> print_type t ) ;
	print_endline " }";
	
	print_string "{ Constructor : " ;
	( match cl.cl_constructor with None -> () | Some ( cl_field ) -> print_class_field cl_field ) ;
	print_endline " }";
	
	print_string "{ Init : " ;
	( match cl.cl_init with None -> () | Some ( expr ) -> print_expr expr ) ;
	print_endline " }";
	
	print_string "{ Overrides : " ;
	List.iter (fun str -> print_string ("'" ^ str ^ "' ")) cl.cl_overrides;
	print_endline " }";

and print_enum_field ef =
	print_string "[ Name : " ;
	print_string ef.ef_name ;
	print_endline(" ]");
	
	print_string "[ Type : " ;
	print_type ef.ef_type ;
	print_endline(" ]");
	
	print_string "[ Pos : " ;
	print_pos ef.ef_pos ;
	print_endline(" ]");
	
	print_string "[ Documentation : " ;
	(match ef.ef_doc with None -> () | Some ( doc ) -> print_endline doc) ;
	print_endline(" ]");
					
	print_string "[ Index : " ;
	print_int ef.ef_index ;
	print_endline(" ]");

and print_def d =
	print_string "{ Def path : " ;
	print_path d.t_path ;
	print_endline " }";
	
	print_string "{ Documentation : " ;
	(match d.t_doc with None -> () | Some ( doc ) -> print_string doc) ;
	print_endline " }";
	
	print_endline ( "{ Private? : " ^ (string_of_bool d.t_private) ^ " }" ) ;
					
	print_string "{ Parameter Types : " ;
	let print_types = function ( a, b ) ->
					print_string a ;
					print_type b
	in List.iter print_types d.t_types ;
	print_endline " }";
					
	print_string "{ Type : " ;
	print_type d.t_type;
	print_endline " }"

and print_enum e =
	print_string "[ Enum path : " ;
	print_path e.e_path ;
	print_endline(" ]");
	
	print_string "[ Pos : " ;
	print_pos e.e_pos ;
	print_endline(" ]");

	print_string ( "[ Documentation : " ^ ( match e.e_doc with
						| None -> ""
						| Some ( doc ) -> doc ) ) ;
	print_endline(" ]");
	
	print_endline ( "[ Private? : " ^ ( string_of_bool e.e_private ) ^ " ]" ) ;
	print_endline ( "[ Extern? : " ^ ( string_of_bool e.e_extern ) ^ " ]" ) ;
	
	print_string "[ Types : " ;
	let print_types = function ( a, b ) ->
				print_string (a ^ " , ") ;
				print_type b
	in List.iter print_types e.e_types	;
	print_endline(" ]");
	
	print_string "[ Enum Constructors : " ;
	let print_constrs str efield =
		print_string (str ^ " , ") ;
		print_enum_field efield
	in PMap.iter print_constrs e.e_constrs ;
	print_endline(" ]");

	print_string "[ Names : " ;
	List.iter ( fun en -> print_string (en ^ " , ")) e.e_names;
	print_endline(" ]")


and print_module_type = function
	| TClassDecl ( cla ) -> print_string "[ TClassDecl : " ;print_path cla.cl_path ; print_string " ]"
	| TEnumDecl ( enum ) -> print_string "[ TEnumDecl : " ;print_path enum.e_path; print_string " ]"
	| TTypeDecl ( def ) -> print_string "[ TTypeDecl : " ;print_path def.t_path; print_string " ]"